package gconsts

import (
	"context"
	"reflect"

	log "gitee.com/abril-cx/gtools/glog"
	mongo "gitee.com/abril-cx/gtools/gmongo"
	utils "gitee.com/abril-cx/gtools/gutils"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo/options"
)

var (
	ModelData = map[string]interface{}{}
)

func MigrationModel(model_data map[string]interface{}) error {
	log.Cyan("迁移字段...")
	ModelData = model_data
	// 过滤
	// filter_field_list := []string{"id", "_id", "deleted"}
	filter_field_list := []string{"deleted"}
	cur := mongo.MongoConn.Collection("fields")
	field_map := []bson.M{}
	for key, model := range model_data {
		reflect_model := reflect.TypeOf(model).Elem()
		// 获取结构体字段
		for i := 0; i < reflect_model.NumField(); i++ {
			field := reflect_model.Field(i)
			required_value := false
			field_name := field.Tag.Get("json")
			name_value := field.Tag.Get("name")
			default_value := field.Tag.Get("default")
			required := field.Tag.Get("required")
			bind := field.Tag.Get("model")
			is_bind := field.Tag.Get("is_bind")
			crypto := field.Tag.Get("crypto")
			module := field.Tag.Get("module")
			module_show := field.Tag.Get("module_show")
			multiple := field.Tag.Get("multiple")
			related := field.Tag.Get("related")
			options := field.Tag.Get("options")
			_select := field.Tag.Get("select")
			hidden := field.Tag.Get("hidden")
			hidden_depth := field.Tag.Get("hidden_depth")
			sort := field.Tag.Get("sort")
			span := field.Tag.Get("span")
			desc := field.Tag.Get("desc")
			data_tag := field.Tag.Get("data")
			tree := field.Tag.Get("tree")
			if required == "true" {
				required_value = true
			}
			if utils.InArrayString(filter_field_list, field_name) {
				continue
			}
			field_type_string := ""
			field_type := field.Type.String()
			switch field_type {
			case "primitive.ObjectID":
				field_type_string = "object_id"
			case "[]primitive.ObjectID":
				field_type_string = "object_ids"
			default:
				field_type_string = field_type
			}
			data := bson.M{
				"source":   "system",
				"created":  utils.GetDateTime(0),
				"updated":  utils.GetDateTime(0),
				"deleted":  nil,
				"model":    key,
				"field":    field_name,
				"name":     name_value,
				"types":    field_type_string,
				"required": required_value,
				"transmit": false,
			}
			if related != "" {
				data["related"] = related
			}
			if _select != "" {
				data["select"] = _select
			}
			if tree != "" {
				data["tree"] = tree
			} else {
				data["tree"] = "text"
			}
			if data_tag != "" {
				data["data"] = data_tag
			}
			if options != "" {
				data["options"] = options
			}
			if desc != "" {
				data["desc"], _ = utils.StrToInt64(desc)
			} else {
				data["desc"] = 0
			}
			if hidden != "" {
				if hidden == "true" {
					data["hidden"] = true
				} else {
					data["hidden"] = false
				}
			} else {
				data["hidden"] = false
			}
			if hidden_depth != "" {
				if hidden_depth == "true" {
					data["hidden_depth"] = true
				} else {
					data["hidden_depth"] = false
				}
			} else {
				data["hidden_depth"] = false
			}
			if multiple != "" {
				if multiple == "true" {
					data["multiple"] = true
				} else {
					data["multiple"] = false
				}
			} else {
				data["multiple"] = false
			}
			if default_value != "" {
				data["default"] = default_value
			} else {
				data["default"] = nil
			}
			if sort != "" {
				data["sort"] = sort
			}
			if span != "" {
				data["span"], _ = utils.StrToInt64(span)
			} else {
				data["span"] = 1
			}
			if module != "" {
				data["module"] = module
			} else {
				if field_name == "created" || field_name == "updated" || field_name == "deleted" {
					data["module"] = "datetime"
				} else if field_name == "remark" {
					data["module"] = "textarea"
				} else {
					switch field.Type.Name() {
					case "string":
						data["module"] = "text"
					case "int", "int8", "int16", "int32", "int64":
						data["module"] = "number"
					case "float32", "float64":
						data["module"] = "text"
					case "bool":
						data["module"] = "boolean"
					}
				}
			}
			if module_show != "" {
				if module_show == "false" {
					data["module_show"] = false
				} else {
					data["module_show"] = true
				}
			} else {
				if field_name == "created" || field_name == "updated" || field_name == "deleted" {
					data["module_show"] = false
				} else {
					data["module_show"] = true
				}
			}
			if bind != "" {
				data["bind"] = bind
			} else {
				data["bind"] = nil
			}
			if is_bind != "" {
				if is_bind == "true" {
					data["is_bind"] = true
				} else {
					data["is_bind"] = false
				}
			} else {
				data["is_bind"] = nil
			}
			if crypto != "" {
				if crypto == "true" {
					data["crypto"] = true
				} else {
					data["crypto"] = false
				}
			} else {
				data["crypto"] = nil
			}
			if field_name == "_id" {
				data["name"] = "ID"
				data["module_show"] = false
			}
			field_map = append(field_map, data)
		}
		_, err := cur.DeleteMany(context.Background(), bson.M{
			"source": "system",
			"model":  key,
		})
		if err != nil {
			return err
		}
	}
	for _, field_data := range field_map {
		_, err := cur.UpdateOne(context.Background(), bson.M{
			"model": field_data["model"], "field": field_data["field"],
		}, bson.M{"$set": field_data}, options.Update().SetUpsert(true))
		if err != nil {
			return err
		}
	}
	return nil
}
